classdef LiraFeature < handle
    % Attributes
    properties %(GetAccess=private)
        hPos
        hNeg
        gLength
        gWindowStart
        posCoords
        negCoords
    end
    
    % Constructors
    methods
        function obj=LiraFeature(varargin) 
            % hPos, hNeg, gLength, binImage
            obj.gWindowStart = [];
            
            obj.hPos = varargin{1};
            obj.hNeg = varargin{2};
            obj.gLength = varargin{3};
            obj.buildFeatures(varargin{4});
        end
    end
    
    % Utility methods
    methods
        function buildFeatures(obj, binImage)
            [nRows nCols] = size(binImage);
            
            % Randomize observed points
            foundPoints = false;
            while foundPoints ~= true
                % Randomize G Window start position
                gWindowStartCandidate = {randi(nRows - obj.gLength),...
                    randi(nCols - obj.gLength)};
                
                gWindow = binImage (gWindowStartCandidate{1}:...
                    (gWindowStartCandidate{1}+obj.gLength),...
                    gWindowStartCandidate{2}:...
                    (gWindowStartCandidate{2}+obj.gLength));
                
                [posR, posC] = find(gWindow > 0);
                [negR, negC] = find(gWindow == 0);
                
                posLength = length(posR);
                negLength = length(negR);
                
                if (posLength >= obj.hPos && negLength >= obj.hNeg)
                    posIndexes = randperm(posLength, obj.hPos);
                    negIndexes = randperm(negLength, obj.hNeg);
                    
                    obj.posCoords = zeros(length(posIndexes), 2, 'uint8');
                    for n=1:length(posIndexes)
                        obj.posCoords(n,:) = [(posR(posIndexes(n)) +...
                            gWindowStartCandidate{1} - 1),...
                            (posC(posIndexes(n)) +...
                            gWindowStartCandidate{2} - 1)];
                    end
                    
                    obj.negCoords = zeros(length(negIndexes), 2, 'uint8');
                    for n=1:length(negIndexes)
                        obj.negCoords(n,:) = [(negR(negIndexes(n)) +...
                            gWindowStartCandidate{1} - 1),...
                            (negC(negIndexes(n)) +...
                            gWindowStartCandidate{2} - 1)];
                    end
                    
                    obj.gWindowStart = gWindowStartCandidate;
                    foundPoints = true;
                end               
            end
        end
        
        function hasFeature=hasFeature(obj, inputImage)
            hasFeature = 1;
            posCoordsSliced = obj.posCoords;
            for posCoordIndex=1:length(obj.posCoords)
                coord = posCoordsSliced(posCoordIndex,:);
                if (inputImage(coord(1),coord(2)) < 1)
                    hasFeature = 0;
                    return;
                end
            end
            
            for negCoordIndex=1:length(obj.negCoords)
                coord = obj.negCoords(negCoordIndex,:);
                if (inputImage(coord(1),coord(2)) > 0)
                    hasFeature = 0;
                    return;
                end
            end
        end
    end
    
    % Get and set methods
    methods
        function ret=getHPos(obj)
            ret = obj.hPos;
        end
        function ret=getHNeg(obj)
            ret = obj.hNeg;
        end
        function ret=getGLength(obj)
            ret = obj.gLength;
        end
        function ret=getGWindowStart(obj)
            ret = obj.gWindowStart;
        end
    end
end

